﻿#include <iostream>
#include <atomic>
#include <thread>
#include <vector>
#include <mutex>
#include <queue>
#include <windows.h>
#include <condition_variable>

using namespace std;


// a simple global linked list:一个简单的全局链表
struct Node { int value; Node* next; };
std::atomic<Node*> list_head(nullptr);
void append(int val, int n)
{
	std::this_thread::sleep_for(std::chrono::seconds(1));
	for (int i = 0; i < n; i++)
	{
		// append an element to the list;向列表追加一个元素
		Node* oldHead = list_head;
		Node* newNode = new Node{ val + i,oldHead };
		// what follows is equivalent to: list_head = newNode, but in a thread - safe way :下面的代码等价于：list_head = newNode，但是以线程安全的方式：
		while (!list_head.compare_exchange_weak(oldHead, newNode))
			newNode->next = oldHead;
	}
}
void test1()
{
	// spawn 10 threads to fill the linked list:生成10个线程来填充链表
	std::vector<std::thread> threads;
	threads.emplace_back(append, 0, 10);
	threads.emplace_back(append, 20, 10);
	threads.emplace_back(append, 30, 10);
	threads.emplace_back(append, 40, 10);
	for (auto& th : threads)
		th.join();
	// print contents:打印内容
	for (Node* it = list_head; it != nullptr; it = it->next)
		std::cout << ' ' << it->value;
	std::cout << '\n';
	// cleanup:清理
	Node* it;
	while (it = list_head)
	{
		list_head = it->next;
		delete it;
	}
}
int test2()
{
	std::atomic<int> num(3);

	int oldnum = 3;
	int newnum = 5;
	bool value = num.compare_exchange_weak(oldnum, newnum);
	cout << " value: " << value << " num: " << num << " oldnum: " << oldnum << endl;
	return 0;
}


// ⾃旋锁（SpinLock）是⼀种忙等待的锁机制，适⽤于锁持有时间⾮常短的场景。
// 在多线程编程中，当⼀个线程尝试获取已被其他线程持有的锁时，⾃旋锁会让该
// 线程在循环中不断检查锁是否可⽤，⽽不是进⼊睡眠状态。这种⽅式可以减少上
// 下⽂切换的开销，但在锁竞争激烈或锁持有时间较⻓的情况下，会导致CPU资源的浪费。
// 以下是使⽤C++11实现的⼀个简单⾃旋锁⽰例：
class SpinLock
{
private:
	// ATOMIC_FLAG_INIT默认初始化为false
	std::atomic_flag _flag = ATOMIC_FLAG_INIT;
public:
	void lock()
	{
		// test_and_set将内部值设置为true，并且返回之前的值
		// 第⼀个进来的线程将值原⼦的设置为true，返回false
		// 后⾯进来的线程将原⼦的值设置为true，返回true，所以卡在这⾥空转，
		// 直到第⼀个进去的线程unlock，clear，将值设置为false
		while (_flag.test_and_set(std::memory_order_acquire));
	}
	void unlock()
	{
		// clear将值原⼦的设置为false
		_flag.clear(std::memory_order_release);
	}
};
// 测试⾃旋锁
void worker(SpinLock& lock, int& sharedValue)
{
	lock.lock();
	// 模拟⼀些⼯作
	for (int i = 0; i < 1000000; ++i)
	{
		++sharedValue;
	}
	lock.unlock();
}

void test3()
{
	SpinLock ma_lock;
	int ma_sharedValue = 0;
	std::vector<std::thread> ma_threads;
	// 创建多个线程
	for (int i = 0; i < 4; ++i)
	{
		ma_threads.emplace_back(worker, std::ref(ma_lock), std::ref(ma_sharedValue));
	}
	// 等待所有线程完成
	for (auto& thread : ma_threads)
	{
		thread.join();
	}
	std::cout << "Final shared value: " << ma_sharedValue << std::endl;
}

std::mutex mtx;
std::condition_variable cv;
bool ready = false;
bool is_ready()
{
	return ready;
}
void print_id(int id) {
	std::unique_lock<std::mutex> lck(mtx);
	//while (!ready)cv.wait(lck);
	cv.wait(lck, is_ready);
	std::cout << "thread " << id << '\n';
}
void go() {
	std::unique_lock<std::mutex> lck(mtx);
	ready = true;

	// 通知所有阻塞在条件变量上的线程
	cv.notify_all();
}

void test4()
{
	std::thread threads[10];
	// spawn 10 threads:
	for (int i = 0; i < 10; ++i)
		threads[i] = std::thread(print_id, i);
	std::cout << "10 threads ready to race...\n";
	std::this_thread::sleep_for(std::chrono::milliseconds(100));
	go(); // go!
	for (auto& th : threads)
		th.join();
}



//std::mutex mtx;
//std::condition_variable cv;
std::queue<int> data_queue;
bool finished = false; // 条件

// 生产者线程
void producer() {
	for (int i = 0; i < 5; ++i) {
		std::this_thread::sleep_for(std::chrono::milliseconds(100));
		{
			std::lock_guard<std::mutex> lk(mtx);
			data_queue.push(i);
			std::cout << "Produced: " << i << std::endl;
		} // lock_guard 超出作用域，自动释放锁
		cv.notify_one(); // 通知一个消费者
	}
	{
		std::lock_guard<std::mutex> lk(mtx);
		finished = true;
	}
	cv.notify_all(); // 通知所有消费者，工作已完成
}

// 消费者线程
void consumer(int id) {
	while (true) {
		std::unique_lock<std::mutex> lk(mtx);
		// 使用带谓词的wait，安全地处理虚假唤醒
		cv.wait(lk, [] {
			return finished || !data_queue.empty();
			});

		// 检查是否所有工作都已完成且队列为空
		if (finished && data_queue.empty()) {
			break;
		}

		// 从队列中取数据
		int value = data_queue.front();
		data_queue.pop();
		lk.unlock(); // 提前释放锁，让其他线程运行

		std::cout << "Consumer " << id << " consumed: " << value << std::endl;
	}
	std::cout << "Consumer " << id << " exiting." << std::endl;
}

int main() {
	std::thread p(producer);
	std::thread c1(consumer, 1);
	std::thread c2(consumer, 2);

	p.join();
	c1.join();
	c2.join();

	return 0;
}